/* 封装一个对象迭代的方法
  *   + 基于传统的 for/in 循环，会存在一些弊端
  *   「性能较差；既可以迭代私有的，也可以迭代共有的；只能迭代"可枚举，非Symbol类型的属性..."」
  *   + 解决思路：获取对象所有的私有属性「私有的，不论是否可枚举，不论类型」
  *       Object.getOwnPropertyNames(arr)  -> 获取对象非Symbol类型的私有属性「无关是否可枚举」
  *       Object.getOwnPropertySymbols(arr)   -> 获取对象Symbol类型的私有属性
  *       获取所有的私有属性
  *          Object.getOwnPropertyNames(arr).concat(Object.getOwnPropertySymbols(arr))
          也可以基于ES6的Reflect.ownKeys 代替上述操作「弊端：不兼容IE」
  */

// Array.prototype.BB = 200
let arr = [10, 20]
arr[Symbol('AA')] = 100
// console.log(Object.getOwnPropertyNames(arr), 2111);//
// console.log(Object.getOwnPropertySymbols(arr, 2222));
// let keys = Reflect.ownKeys(arr)
// console.log(keys, 333)

// for(let key in arr){
//     console.log(key)
// }

const each = function (obj, callback) {
    if (obj === null || typeof obj !== 'object') return obj
    if (typeof callback !== 'function') return
    let keys = Reflect.ownKeys(obj);
    /* 兼容IE */
    /*let keys = Object.getOwnPropertyNames(arr).concat(Object.getOwnPropertySymbols(arr))*/
    keys.forEach(key => {
        let value = obj[key]
        // 每一次迭代，都把回调函数执行
        callback(value, key)
    })
}
// each(arr, (value, key) => {
//     console.log(value, key)
// })


/* createElement: 创建虚拟DOM对象 */
export function createElement(ele, props, ...children) {
    let virtualDOM = {
        $$typeof: Symbol('react.element'),
        key: null,
        ref: null,
        type: null,
        props: {}
    };
    let len = children.length;
    virtualDOM.type = ele;
    if (props !== null) {
        virtualDOM.props = {...props};
    }
    if (len === 1) {
        console.log(children[0], 222)
        virtualDOM.props.children = children[0]
    } else if (len > 1) {
        virtualDOM.props.children = children
    }
    return virtualDOM
}

/* render：把虚拟DOM变为真实DOM */

export function render(virtualDOM, container) { // v16
    let {type, props} = virtualDOM
    if (typeof type === 'string') {
        // 存储的是标签名：动态创建这样一个标签
        let ele = document.createElement(type)
        // 为标签设置相关的属性 & 子节点
        each(props, (value, key) => {
            // className 的处理，value存储的是样式类名
            if (key === 'className') {
                ele.className = value
                return;
            }
            // style的处理,value存储的是样式对象
            if (key === 'style') {
                each(value, (val, attr) => {
                    ele.style[attr] = val
                })
                return;
            }
            // 子节点的处理,value存储的children 属性值
            if (key === 'children') {
                let children = value;
                if (!Array.isArray(children)) {
                    children = [children]
                }
                children.forEach(child => {
                    // 子节点是文本节点：直接插入即可
                    if (/^(string|number)$/.test(typeof child)) {
                        ele.appendChild(document.createTextNode(child))
                        return
                    }
                    // 子节点又是一个 virtualDOM：递归处理
                    render(child, ele)
                })
                return;
            }
            ele.setAttribute(key, value)
        })
        // 把新增的标签，增加到指定的容器中
        container.appendChild(ele)
    }
}
